#pragma once

#ifndef __TCP_HELPER_H__
#define __TCP_HELPER_H__

#include "Common.h"
#include "LogManager.h"

// Helper for Tcp communication.
class TcpHelper
{
public:
	// Construct TcpHelper with given address, port and display message delegate.
	TcpHelper(const string& address, const string& port);

	// Finalize TcpHelper.
	~TcpHelper();

	// Try to connect to the server.
	bool TryConnect();

	// Disconnect from the server.
	bool TryDisconnect();

	// Try to send a buffer to the server.
	bool TrySend(vector<char>& buffer);

	// Read a value of a generic type from the server.
	template<typename T>
	bool TryRead(T& result);

	// Try to read a string from the server.
	template<>
	bool TryRead(string& result);

private:
	bool m_connected;
	string m_address;
	string m_port;
	SOCKET m_socket;

	// Try to initialize Winsock.
	bool TryInitializeWinsock();

	// Try to resolve the server address and port.
	bool TryResolveAddressInfo(PADDRINFOW& result);

	// Attempt to connect to an address list until one succeeds.
	bool TryConnectAddress(const PADDRINFOW& address);

	// Try to create a socket for connecting to server.
	bool TryCreateSocket(const PADDRINFOW& address);

	// Try to connect to server.
	bool TryConnectServer(const PADDRINFOW& address);

	// Read a value of a generic type with a specified length from the server.
	template<typename T>
	bool TryRead(T& result, int length);

	// Try to reads in a 32-bit integer in compressed format.
	bool TcpHelper::TryRead7BitEncodedInt(int& result);

	// Print the error message and clean the managed resources.
	bool HandleError(const string& message);

	// Print the error message and clean the managed resources.
	bool HandleError(const string& message, const int& error);

	// Print the error message, close the socket and clean the managed resources.
	bool HandleErrorAndClose(const string& message);

	// Print the error message then try to disconnect from the server.
	bool HandleErrorAndDisconnect(const string& message);
};

#endif  // __TCP_HELPER_H__